#include "ParticleSystem.h"
#include "tinyxml.h"
#include "Flyweight.h"

ParticleSystem::ParticleSystem()
{

}

ParticleSystem::~ParticleSystem()
{
	m_ActiveEmitter.GetAliveVec().clear();
	m_ActiveEmitter.GetFlyweight()->Release();
}


void ParticleSystem::Update(float dt)
{
	m_ActiveEmitter.Update(dt);

}

void ParticleSystem::Render()
{
	m_ActiveEmitter.Render();
}

bool ParticleSystem::Load(const char* filename, ParticleSystem& ps, BaseObject& owner)
{
	int tempInt;

	// Create a TinyXML Document
	TiXmlDocument doc;

	// Attempt to load from the file
	if (doc.LoadFile(filename) == false)
		return false;


	// Access the 'root' TinyXML Element
	TiXmlElement* pRoot = doc.RootElement();

	if (pRoot == nullptr)
		return false;


	//Set up the particle's flyweight first
	TiXmlElement* pInfo = pRoot->FirstChildElement("Flyweight");
	
	//Initialize flyweight and get the Image ID
	Flyweight fw(owner);

	pInfo = pInfo->FirstChildElement("ImageID");
	const char* pName = pInfo->GetText();
	if (pName != nullptr)
	{
		std::string fileName = "resource//graphics//";
		fileName += pName;
		fw.SetImageID(fileName.c_str());
	}

	//Load the flyweights image
	fw.LoadTexture();
	
	//Go To Next Element
	pInfo = pInfo->NextSiblingElement("ImageDimensions");
	//Get width
	pInfo->Attribute("width", &tempInt);
	//Set Width
	fw.SetTextureWidth((unsigned int)tempInt);
	//Get Height
	pInfo->Attribute("height", &tempInt);
	//Set Height
	fw.SetTextureHeight((unsigned int)tempInt);


	//Get Particle color for the flyweight
	pInfo = pInfo->NextSiblingElement("Color");
	
	//Create temporary Color
	SGD::Color tempColor;
	double temp;
	float tempFloat;

	//Load in red
	pInfo->Attribute("r", &temp);
	tempColor.red = (unsigned char)temp;
	//Load in Green
	pInfo->Attribute("g", &temp);
	tempColor.green = (unsigned char)temp;
	//Load in Blue
	pInfo->Attribute("b", &temp);
	tempColor.blue = (unsigned char)temp;
	//Load in Alpha
	pInfo->Attribute("a", &temp);
	tempColor.alpha = (unsigned char)temp;
	//Set Flyweight Color
	fw.SetColor(tempColor);

	//Go to next element
	pInfo = pInfo->NextSiblingElement("Scale");
	//Load in particle scale
	pInfo->QueryFloatAttribute("size", &tempFloat);
	//Set Flyweight scale
	fw.SetScale((float)tempFloat);

	//Go to velocity
	pInfo = pInfo->NextSiblingElement("Velocity");
	//Create temp velocity vec
	SGD::Vector tempVector;
	//Get velocity x
	pInfo->Attribute("minX", &tempInt);
	//Set Velocity x
	tempVector.x = (float)tempInt;
	//Get velocity y
	pInfo->Attribute("minY", &tempInt);
	//Set Velocity y
	tempVector.y =  (float)tempInt;
	//Set velocity
	fw.SetMinVelocity(tempVector);

	//Get velocity x
	pInfo->Attribute("maxX", &tempInt);
	//Set Velocity x
	tempVector.x = (float)tempInt;
	//Get velocity y
	pInfo->Attribute("maxY", &tempInt);
	//Set Velocity y
	tempVector.y = (float)tempInt;
	//Set velocity
	fw.SetMaxVelocity(tempVector);

	//Go to next element
	pInfo = pInfo->NextSiblingElement("Rotation");
	//Get rotation
	pInfo->Attribute("rot", &temp);
	//Set Rotation
	fw.SetRotation((float)temp);

	//Go to next element
	pInfo = pInfo->NextSiblingElement("LifeSpan");
	//Get min lifespan
	pInfo->Attribute("min", &temp);
	//Set min life span
	fw.SetMinLife((float)temp);
	//Get max life span
	pInfo->Attribute("max", &temp);
	//Set Max life span
	fw.SetMaxLife((float)temp);

	//Go to next element
	pInfo = pInfo->NextSiblingElement("ChangeVars");
	//Get Red color change
	pInfo->Attribute("colorR", &temp);
	//Set Red Color Change
	tempColor.red = (unsigned char)temp;
	//Get Green Color Change
	pInfo->Attribute("colorG", &temp);
	//Set Green Color Change
	tempColor.green = (unsigned char)temp;
	//Get Blue color
	pInfo->Attribute("colorB", &temp);
	//Set Blue Color
	tempColor.blue = (unsigned char)temp;
	//Get Alpha
	pInfo->Attribute("colorA", &temp);
	//Set Alpha
	tempColor.alpha = (unsigned char)temp;
	//Set FlyWeight ChangeInColor
	fw.SetChangeInColor(tempColor);

	//Get Change in scale
	pInfo->Attribute("scale", &temp);
	//Set Change in scale
	fw.SetChangeInScale((float)temp);

	//Get Change in rotation
	pInfo->Attribute("rotation", &temp);
	//Set Change in rotation
	fw.SetChangeInRotation((float)temp);

	//Get Change in velocity.x
	pInfo->Attribute("velX", &tempInt);
	//Set change in velocity.x
	tempVector.x = (float)tempInt;

	//Get Change in velocity.y
	pInfo->Attribute("velY", &tempInt);
	//Set Change in velocity.y
	tempVector.y = (float)tempInt;

	//Set change in velocity
	fw.SetChangeInVelocity(tempVector);
	

	//Stop Loading FlyWeight and move to Emitter
	pInfo = pRoot->FirstChildElement("Flyweight");
	pInfo = pInfo->NextSiblingElement("Emitter");

	//Go to next element
	pInfo = pInfo->FirstChildElement("MaxParticles");
	//Get num of max particles
	pInfo->Attribute("num", &temp);

	//Create Emitter to store temporary data into, give it flyweight
	Emitter tempEmitter(fw, (float)temp);
	tempEmitter.SetOwner(&owner);

	//Go to next element
	pInfo = pInfo->NextSiblingElement("SpawnRate");
	//Get spawn rate
	pInfo->QueryFloatAttribute("rate", &tempFloat);
	//Set Spawn Rate
	tempEmitter.SetSpawnRate((float)tempFloat);

	//Go to next element
	pInfo = pInfo->NextSiblingElement("Position");
	//Create temp vec
	SGD::Vector tempPosVec;
	//Get position.x
	pInfo->Attribute("x", &temp);
	//Set position.x
	tempPosVec.x = (float)temp;
	//Get position.y
	pInfo->Attribute("y", &temp);
	//Set position.y
	tempPosVec.y = (float)temp;

	tempEmitter.SetOffsetX((int)tempPosVec.x);
	tempEmitter.SetOffsetY((int)tempPosVec.y);

	//Go to next element
	pInfo = pInfo->NextSiblingElement("IsLooping");
	//Get looping bool
	pInfo->Attribute("bool", &temp);
	//Decode the number
	if (temp != 0.0f)
		tempEmitter.SetLooping(true);
	else
		tempEmitter.SetLooping(false);

	//Go to next element
	pInfo = pInfo->NextSiblingElement("Shape");
	//Get Number that represents the Shape
	pInfo->Attribute("num", &tempInt);
	//Set the shape number
	tempEmitter.SetShape(tempInt);

	
	//Go to next element
	pInfo = pInfo->NextSiblingElement("Dimensions");
	//Get width
	pInfo->Attribute("width", &temp);
	//Set width
	tempEmitter.SetWidth((int)temp);
	//Get height
	pInfo->Attribute("height", &temp);
	//Set height
	tempEmitter.SetHeight((int)temp);
	//Get radius
	pInfo->Attribute("radius", &temp);
	//Set radius
	tempEmitter.SetRadius((int)temp);

	m_ActiveEmitter = tempEmitter;

	return true;
}